package com.example.springboot3demo.controller;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.example.springboot3demo.config.IpnProperty;
import com.example.springboot3demo.converter.R;
import com.example.springboot3demo.google.oauth.OAuthGoogleClient;
import com.example.springboot3demo.utils.AssertUtil;
import com.google.api.client.googleapis.GoogleUtils;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.calendar.Calendar;
import com.google.api.services.calendar.model.CalendarList;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.AccessToken;
import com.google.auth.oauth2.GoogleCredentials;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthUser;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.security.GeneralSecurityException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Tag(name = "Google Controller")
@RestController
@RequestMapping("/google")
@RequiredArgsConstructor
@Slf4j
public class GoogleAuthorizeController {

    public static final String GOOGLE_OAUTH_STATE = "GOOGLE_OAUTH_STATE:%s";
    public static final String GOOGLE_ACCESS_TOKEN = "GOOGLE_ACCESS_TOKEN";


    private final OAuthGoogleClient authGoogleClient;
    private final StringRedisTemplate redisTemplate;

    private final IpnProperty ipnProperty;


    @GetMapping("/oauth/callback")
    @Operation(summary = "[WEB2 Google OAuth] Google OAuth 回调")
    public R<Object> callbackGoogle(@RequestParam(value = "state") String state, @RequestParam("code") String code) {
        String cacheState = redisTemplate.opsForValue().get(String.format(GOOGLE_OAUTH_STATE, state));
        if (StrUtil.isBlank(cacheState)) {
            throw new RuntimeException("state失效");
        }
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        Map<String, String[]> parameterMap = request.getParameterMap();
        log.info("parameterMap = {}", JSONUtil.toJsonStr(parameterMap));
        AuthUser authUser = authGoogleClient.requestAuthorizeLogin(
                AuthCallback.builder()
                        .state(state)
                        .code(code)
                        .build()
        );
        String accessToken = authUser.getToken().getAccessToken();
        AssertUtil.isTrue(StrUtil.isNotBlank(accessToken), "accessToken error");
        redisTemplate.opsForValue().set(GOOGLE_ACCESS_TOKEN, accessToken, 50, TimeUnit.MINUTES);
        return R.success(authUser);
    }

    @GetMapping("/oauth/google")
    @Operation(summary = "获取 Google OAuth 链接")
    public R<Object> oauthGoogle() {
        String state = RandomUtil.randomString(10);
        log.info("state = {}", state);
        redisTemplate.opsForValue().set(String.format(GOOGLE_OAUTH_STATE, state), state, 5, TimeUnit.MINUTES);
        String url = authGoogleClient.requestAuthorizeURL(state);
        return R.success(url);
    }


    @GetMapping("/calendar/list")
    @Operation(summary = "获取Google日历列表")
    public R<Object> calendarList(@RequestParam(value = "accessToken") String accessToken) throws GeneralSecurityException, IOException {
        GoogleCredentials credentials = GoogleCredentials.create(AccessToken.newBuilder().setTokenValue(accessToken).build());
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7890));
        HttpTransport httpTransport = new NetHttpTransport.Builder().setProxy(proxy).trustCertificates(GoogleUtils.getCertificateTrustStore()).build();
        Calendar client = new Calendar.Builder(
                httpTransport,
                //GoogleNetHttpTransport.newTrustedTransport(),
                GsonFactory.getDefaultInstance(),
                new HttpCredentialsAdapter(credentials)
        ).setApplicationName("calendar Test").build();
        CalendarList calendarList = client.calendarList().list().execute();
        return R.success(calendarList.getItems());
    }

}
